﻿using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Common.Security
{
    public class SM4Encrypt
    {
        /// <summary>
        /// 加密ECB模式
        /// </summary>
        /// <param name="secretKey">密钥</param>
        /// <param name="hexString">明文是否是十六进制</param>
        /// <param name="plainText">明文</param>
        /// <returns>返回密文</returns>
        public static string Encrypt_ECB(string secretKey, bool hexString, string plainText)
        {
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_ENCRYPT;
            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
            }
            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Encoding.UTF8.GetBytes(plainText));
            //string cipherText = Encoding.UTF8.GetString(Hex.Encode(encrypted));
            string cipherText =Convert.ToBase64String(encrypted);


            return cipherText;
        }

        /// <summary>
        /// 解密ECB模式
        /// </summary>
        /// <param name="secretKey">密钥</param>
        /// <param name="hexString">明文是否是十六进制</param>
        /// <param name="cipherText">密文</param>
        /// <returns>返回明文</returns>
        public static string Decrypt_ECB(string secretKey, bool hexString, string cipherText)
        {
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_DECRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
            }

            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Hex.Decode(cipherText));
            return Encoding.UTF8.GetString(decrypted);
        }

        /// <summary>
        /// 加密CBC模式
        /// </summary>
        /// <param name="secretKey">密钥</param>
        /// <param name="hexString">明文是否是十六进制</param>
        /// <param name="iv"></param>
        /// <param name="plainText">明文</param>
        /// <returns>返回密文</returns>
        public static string Encrypt_CBC(string secretKey, bool hexString, string iv, string plainText, string encoding = "utf-8", int needEnCode = 1)
        {
            if (String.IsNullOrWhiteSpace(encoding))
            {
                encoding = "utf-8";
            }
            if (encoding == "GBK" || encoding == "GB2312")
            {
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            }
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_ENCRYPT;
            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
                ivBytes = Encoding.UTF8.GetBytes(iv);
            }
            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Encoding.GetEncoding(encoding).GetBytes(plainText));
            if (needEnCode == 1)
            {
                encrypted = Hex.Encode(encrypted);
            }
            else if (needEnCode == 2)
            {
                encrypted = Base64.Encode(encrypted);
            }
            string cipherText = Encoding.UTF8.GetString(encrypted);
            return cipherText;
        }

        /// <summary>
        /// 解密CBC模式
        /// </summary>
        /// <param name="secretKey">密钥</param>
        /// <param name="hexString">明文是否是十六进制</param>
        /// <param name="iv"></param>
        /// <param name="cipherText">密文</param>
        /// <returns>返回明文</returns>
        public static string Decrypt_CBC(string secretKey, bool hexString, string iv, string cipherText)
        {
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_DECRYPT;
            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
                ivBytes = Encoding.UTF8.GetBytes(iv);
            }
            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Hex.Decode(cipherText));
            return Encoding.UTF8.GetString(decrypted);
        }

        /// <summary>
        /// 加密ECB模式 BASE64
        /// </summary>
        /// <param name="secretKey"></param>
        /// <param name="hexString"></param>
        /// <param name="plainText"></param>
        /// <returns></returns>
        public static string Encrypt_ECB_Base64(string secretKey, bool hexString, string plainText)
        {
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_ENCRYPT;
            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
            }
            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Encoding.UTF8.GetBytes(plainText));
            string cipherText = Encoding.UTF8.GetString(Base64.Encode(encrypted));
            return cipherText;
        }

        /// <summary>
        /// 解密ECB模式 BASE64
        /// </summary>
        /// <param name="secretKey"></param>
        /// <param name="hexString"></param>
        /// <param name="plainText"></param>
        /// <returns></returns>
        public static string Decrypt_ECB_Base64(string secretKey, bool hexString, string cipherText)
        {
            if (String.IsNullOrWhiteSpace(cipherText) || String.IsNullOrWhiteSpace(secretKey)) return null;
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_DECRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
            }

            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Base64.Decode(cipherText));
            return Encoding.UTF8.GetString(decrypted);
        }
    }
}
